home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / tex / dvi / dvist3_3.arc / SERVER.C < prev    next >
C/C++ Source or Header  |  1989-05-03  |  11KB  |  609 lines

  1. /*
  2.     Remote file server written by Avygdor Moise and Tyler Ivanco
  3.     Copyright by Avygdor moise and Tyler Ivanco Mar 1987, all rights
  4.     reserved.
  5.  
  6.     We release this program into the public domain with the following
  7.     restrictions:
  8.  
  9.     This program may be freely distributed free of charge in source
  10.     and in binary, provided that the copyright notice is preserved
  11.     in the body of the program and any printed documentation that
  12.     is included with the client/server programs.
  13.     
  14.     This program MAY not be sold or become a part of a commercial package
  15.     without prior WRITTEN authorization from the authors.
  16.     
  17.     You may add new features and extensions to this software provided
  18.     that you notify the authors, so we can update our own original to
  19.     ensure that only one version of this program is circulating among the
  20.     various users.
  21.     
  22.     The authors may be reached at
  23.     
  24.         York University
  25.         Center for Research in Experimental Space Science
  26.         North York
  27.         Ontario, Canada.
  28.     
  29.     and via EMAIL
  30.     
  31.     BITNET: FS300013@SOL
  32.             FS300022@SOL
  33.     
  34.     USENET: mnetor!yetti!gen1!tyler
  35.             mnetor!yetti!yugas!avy
  36.  
  37. */
  38.  
  39. #ifdef VMS
  40. # include stdio
  41. #else
  42. # include <stdio.h>
  43. # ifdef OSK
  44. #  include <sgstat.h>
  45. #  define _IOEOF _EOF
  46. # endif
  47. #endif
  48.  
  49. #ifndef    STDIN
  50. # define STDIN 1    /* So that server can be started by a shell script */
  51. #endif
  52.  
  53. extern FILE *fopen();
  54. extern long ftell();
  55. extern int errno;
  56.  
  57. #define    TRUE    (1)
  58. #define    FALSE    (0)
  59.  
  60. #define    EOR        (0x0D)
  61. #define EOL        (0x0A)
  62. #define    XON        (0x11)
  63. #define    XOFF    (0x13)
  64.  
  65. #ifdef    DEBUG1
  66. # define DEBUG
  67. #endif
  68.  
  69. #ifdef    DEBUG
  70. # define ACK    'A'
  71. # define NAK    'N'
  72. #else
  73. # define    ACK        (0x06)
  74. # define    NAK        (0x15)
  75. #endif
  76.  
  77. #define    E_OK        '0'
  78. #define    E_CHECK        '1'
  79. #define E_INVREQ    '2'
  80. #define    E_READ        '3'
  81. #define    E_WRITE        '4'
  82. #define    E_OPEN        '5'
  83. #define E_EOF        '6'
  84. #define E_NOFILE     '7'
  85. #define E_SEEK         '8'
  86.  
  87. #define PACKET_SIZE    (256)
  88. #define    BUF_SIZE    (2*PACKET_SIZE + 10)
  89. #define MAX_FILES    (16)
  90.  
  91. #define    loop    for(;;)
  92.  
  93. char    inp_buf[BUF_SIZE],out_buf[BUF_SIZE],tmp_buf[BUF_SIZE];
  94. FILE    *file[MAX_FILES];
  95. int    nfiles,packet_len;
  96.  
  97. main()
  98. {
  99.     init();    
  100.  
  101.     loop
  102.     {
  103.         if( get_packet() ) switch( inp_buf[0] )    /* got a valid packet */
  104.         {
  105.         case '?':    /* inquire */
  106.             pos_ack();
  107.             break;
  108.  
  109.         case ACK:    /* sync */
  110.             break;
  111.  
  112.         case 'i':    /* initalize - close all files */
  113.             close_all_req();
  114.             break;
  115.  
  116.         case 'e':    /* end - terminate server */
  117.             exit_req();
  118.             break;
  119.  
  120.         case 'o':    /* open file */
  121.             open_req();
  122.             break;
  123.  
  124.         case 'c':    /* close file */
  125.             close_req();
  126.             break;
  127.  
  128.         case 'r':    /* read data */
  129.             read_req();
  130.             break;
  131.  
  132.         case 'w':    /* write data */
  133.             write_req();
  134.             break;
  135.  
  136.         case 's':    /* seek to byte */
  137.             seek_req();
  138.             break;
  139.  
  140.         case 't':    /* tell current position */
  141.             tell_req();
  142.             break;
  143.  
  144.         default:
  145.             neg_ack(E_INVREQ);
  146.         }
  147.         else
  148.         {
  149.             if( strncmp(inp_buf,"exit",4) == 0 ) exit_req();
  150.             neg_ack(E_CHECK);
  151.         }
  152.     }
  153. }
  154.  
  155. neg_ack(err)
  156.     int    err;
  157. {
  158.     char c;
  159.     c = NAK;
  160.     write(1,&c,1);
  161.     c = err;
  162.     write(1,&c,1);
  163. #ifdef    DEBUG1
  164.     fprintf(stderr,"neg_ack called err = %d.\n",err);
  165. #endif
  166. }
  167.  
  168. pos_ack()
  169. {
  170.     char c;
  171.     c = ACK;
  172.     write(1,&c,1);
  173. #ifdef    DEBUG1
  174.     fprintf(stderr,"pos_ack called.\n");
  175. #endif
  176. }
  177.  
  178. int get_packet()
  179. {
  180.     int i,j,ret;
  181.     char c;
  182. #ifdef DEBUG1
  183.     fprintf(stderr,"Enter get_packet:\n");fflush(stderr);
  184. #endif
  185.     ret = FALSE;
  186.  
  187.     for(i=0; i<BUF_SIZE; i++)
  188.     {
  189.         read(STDIN,&c,1);
  190. #ifdef    DEBUG1
  191.         fprintf(stderr,"[%02x]",(int)c & 0xff); fflush(stderr);
  192. #endif
  193.         if( c == ACK )    /* unconditional quit */
  194.         {
  195.             inp_buf[0] = ACK;
  196.             ret = TRUE;
  197.             break;
  198.         }
  199.  
  200.         if( (c == EOR) || (c == EOL) )        /* at end of packet */
  201.         {
  202.             if( i >= 2 )            /* at least 3 bytes <cmd><chk><EOR> */
  203.             {
  204.                 packet_len = --i;        /* drop the EOR byte */
  205.                 for(j=c=0; j<i; j++)    /* compute checksum */
  206.                 {
  207.                     c += inp_buf[j];
  208.                 }
  209. #ifdef DEBUG
  210.                 if(inp_buf[i] != '.')
  211. #else
  212.                 if( c != inp_buf[i] )
  213. #endif
  214.                 {
  215. #ifdef DEBUG1
  216.                     fprintf(stderr,
  217.                      "\nget_packet: bad checksum - c=[%02x], inp=[%02x]\n",
  218.                         c & 0xff, inp_buf[i] & 0xff);
  219. #endif
  220.                     c = EOR;
  221.                     break;
  222.                 }
  223.  
  224.                 inp_buf[i] = '\0';    /* make it a string */
  225.                 ret = TRUE;            /* good record */
  226.                 break;
  227.             }
  228.             else
  229.                 break;
  230.         }
  231.         if( c == '-' )                /* an escape character */
  232.         {
  233.             read(STDIN,&c,1);
  234. #ifdef    DEBUG1
  235.             fprintf(stderr,"[%02x]",(int)c & 0xff); fflush(stderr);
  236. #endif
  237.             if( c == ACK )            /* unconditional quit */
  238.             {
  239.                 inp_buf[0] = ACK;
  240.                 ret = TRUE;
  241.                 break;
  242.             }
  243.             c -= '@';
  244.         }
  245.         inp_buf[i] = c;
  246.     }
  247.     if( ret == FALSE )    /* no EOR ... i.e. buffer overflow */
  248.     {
  249.         
  250.         while( (c != EOR) && (c != EOL) && (c != ACK) )
  251.         {
  252. #ifdef    DEBUG1
  253.             fprintf(stderr,"get_packet: sync loop\n");
  254. #endif
  255.             read(STDIN, &c, 1);
  256. #ifdef    DEBUG1
  257.             fprintf(stderr,"[%02x]",(int)c & 0xff);fflush(stderr);
  258. #endif
  259.         }
  260.         if( c == ACK )
  261.         {
  262.             inp_buf[0] = ACK;
  263.             ret = TRUE;
  264.         }
  265.         else
  266.             ret = FALSE;
  267.     }
  268. #ifdef    DEBUG1
  269.     fprintf(stderr,"\nget_packet: ret = %d\n",ret);
  270. #endif
  271.     return(ret);
  272. }
  273.  
  274. reply(buffer,count)
  275.     char *buffer;
  276.     int    count;
  277. {
  278.     int i,j;
  279.     char sum,c;
  280.  
  281. #ifdef DEBUG1
  282.         fprintf(stderr,"Enter reply: buffer length = %d\n",count);
  283. #endif
  284.     out_buf[0] = sum = 'd';
  285.  
  286.     for(i=0,j=1; i<count; i++)
  287.     {
  288.         c = buffer[i];
  289.  
  290.         sum += c;        /* checksum on true data not trasformed one */
  291.         switch( c )
  292.         {
  293.         case ACK:
  294.         case NAK:
  295.         case EOR:
  296.         case EOL:
  297.         case XON:
  298.         case XOFF:
  299.         case '-':
  300.             out_buf[j++] = '-';
  301.             out_buf[j++] = buffer[i] + '@';
  302.             break;
  303.         default:
  304.             out_buf[j++]= buffer[i];
  305.         }
  306.     }
  307. #ifdef DEBUG
  308.     out_buf[j++] = '.';
  309. #else
  310.     if(( (sum & 0xE0) == 0 ) || (sum == '-'))
  311.     {
  312.         out_buf[j++] = '-';
  313.         sum += '@';
  314.     }
  315.     out_buf[j++] = sum;
  316. #endif
  317.     out_buf[j++] = EOL;
  318.  
  319.     loop
  320.     {
  321.         write(1,out_buf,j);        /* send the data */
  322. #ifdef DEBUG1
  323.         fprintf(stderr,"reply: out_buf length = %d\n",j);
  324.         for(i=0; i<j; i++) fprintf(stderr,"[%02x]", (int)out_buf[i] & 0xff);
  325.         fprintf(stderr,"\n");
  326. #endif
  327.         read(STDIN,&sum,1);            /* await ACK */
  328. #ifdef    DEBUG1
  329.         fprintf(stderr,"reply: expecting ACK, got [%02x]\n",(int)sum & 0xff);
  330. #endif
  331.         switch(sum)
  332.         {
  333.         case NAK:                /* not received try again */
  334.             break;
  335.         case ACK:                /* received O.K. so quit */
  336.             return;
  337.         }
  338.     }
  339. }
  340.  
  341. init()
  342. {
  343.     int i;
  344.  
  345.     sysinit();
  346.  
  347.     for(i=0; i<MAX_FILES; i++)
  348.     {
  349.         file[i] = (FILE *)0;
  350.     }
  351.     nfiles = 0;
  352. #ifdef    DEBUG1
  353.     fprintf(stderr,"init called.\n");
  354. #endif
  355. }
  356.  
  357. close_all_req()
  358. {
  359.     int i;
  360.  
  361.     for(i=0; i<MAX_FILES; i++)
  362.     {
  363.         if(file[i])
  364.         {
  365.             fclose(file[i]);
  366.             file[i] = (FILE *)0;
  367.         }
  368.     }
  369.     nfiles = 0;
  370.     pos_ack();
  371. #ifdef    DEBUG1
  372.     fprintf(stderr,"close_all_req called.\n");
  373. #endif
  374. }
  375.  
  376. exit_req()
  377. {
  378.     close_all_req();
  379.     systerm();
  380. #ifdef    DEBUG1
  381.     fprintf(stderr,"exit_req called.\n");
  382. #endif
  383.     exit(0);
  384. }
  385.  
  386. open_req()    /* <o><mode><filename> */
  387. {
  388.     int i,rewind;
  389.     char *mode;
  390.     FILE *fp;
  391.  
  392. #ifdef    DEBUG1
  393.     fprintf(stderr,"open_req called '%s'.\n",inp_buf);
  394. #endif
  395.     rewind = 0;
  396.  
  397.     switch(inp_buf[1])
  398.     {
  399.     case 'r':
  400.         mode = "r";
  401.         break;
  402.     case 'w':
  403.         mode = "w";
  404.         break;
  405.     case 'u':
  406.         mode = "r+";
  407.         break;
  408.     case 'c':
  409.         mode = "w+";
  410.         break;
  411.     case 'a':
  412.         mode = "r+";
  413.         rewind = 2;
  414.         break;
  415.     default:
  416.         neg_ack(E_INVREQ);
  417.         return;
  418.     }
  419.  
  420.     if( (nfiles > MAX_FILES) || ((fp=fopen(&inp_buf[2],mode)) == (FILE *)0) )
  421.     {
  422.         neg_ack(E_OPEN);
  423.         return;
  424.     }
  425.  
  426.     fseek(fp, 0L, rewind);
  427.  
  428.     for(i=0; i<MAX_FILES; i++)
  429.     {
  430.         if( file[i] == (FILE *)0 ) break;
  431.     }
  432.     file[i] = fp;
  433.     nfiles++;
  434.  
  435.     tmp_buf[0] = i + '@';
  436.     pos_ack();
  437.     reply(tmp_buf,1);
  438. }
  439.  
  440. close_req()        /* <c><filedes> */
  441. {
  442.     int i;
  443.  
  444. #ifdef    DEBUG1
  445.     fprintf(stderr,"close_req called '%c'.\n",inp_buf[1] & 0xff);
  446. #endif
  447.     i = inp_buf[1] - '@';
  448.  
  449.     if( (i>=0) && (i<MAX_FILES) && file[i] )
  450.     {
  451.         fclose(file[i]);
  452.         nfiles--;
  453.         file[i] = (FILE *)0;
  454.         pos_ack();
  455.     }
  456.     else
  457.         neg_ack(E_NOFILE);
  458. }
  459.  
  460. seek_req()
  461. {
  462.     int i,rewind;
  463.     long pos;
  464.  
  465. #ifdef    DEBUG1
  466.     fprintf(stderr,"seek_req called '%c'.\n",inp_buf[1] & 0xff);
  467. #endif
  468.     i = inp_buf[1] - '@';
  469.  
  470.     if( (i>=0) && (i<MAX_FILES) && file[i] )
  471.     {
  472.         pos =